#include "../cominc/ctask.h"
#include "../cominc/cli.h"

static TaskObj TASK_LIST[TASK_LIST_MAX];
static void UnregTask(TaskObj* taskSlot);

void TaskInit(void)
{
    for (size_t idx = 0; idx < TASK_LIST_MAX; idx++) {
        TASK_LIST[idx].idx = idx;
        TASK_LIST[idx].dataBody = NULL;
        TASK_LIST[idx].len = 0;
        TASK_LIST[idx].exe = NULL;
        TASK_LIST[idx].sta = IDLE;
    }
}

void TaskDump(void)
{
    LOG("\r\n-----TaskDump-----");
    LOG("idleCnt[%u]", CountTaskRemain());
    for (size_t idx = 0; idx < TASK_LIST_MAX; idx++) {
        TaskObj* task = &TASK_LIST[idx];
        if (task->sta != IDLE) {
            LOG("taskSlot[%2u] sta[%2u] exeAddr[0x%08x] paraAddr[0x%08x] paraLen[%u]",
                idx, task->sta, task->exe, task->dataBody, task->len);
        }
    }
    LOGStr("\r\n");
}

void ExeTask(void)
{
    size_t idleMax = CountTaskRemain();
		if (idleMax == 0) {
				return;
		}
    for (size_t idx = 0; idx < TASK_LIST_MAX; idx++) {
        TaskObj* task = &TASK_LIST[idx];
        if (task->sta == IDLE) {
            continue;
        }
        task->sta = PROCING;
        int ret = task->exe(task->dataBody, task->len);
        UnregTask(task);
        if (ret != ERR_SUCCESS) {
            LOGCritcal("[CTASK] [%u/%u] FAILED with %d", CountTaskRemain(), idleMax, ret);
        }
    }
}

size_t CountTaskRemain(void)
{
    // 返回任务队列剩余数
    size_t idleCnt = 0;
    for (size_t idx = 0; idx < TASK_LIST_MAX; idx++) {
        if (TASK_LIST[idx].sta != IDLE) {
            idleCnt++;
        }
    }
    return idleCnt;
}

int RegTask(TaskHandle exe, const char* dataBody, size_t dataLen)
{
    /* 寻找空闲任务槽位注入 */
    for (TaskObj* taskSlot = TASK_LIST; taskSlot != TASK_LIST + TASK_LIST_MAX; taskSlot++) {
        if (taskSlot->sta != IDLE) {
            continue;
        }
        taskSlot->dataBody = dataBody; // 零拷贝注册任务
        taskSlot->len = dataLen;
        taskSlot->exe = exe;
        taskSlot->sta = INITING;
        return ERR_SUCCESS;
    }
    LOGCritcal("[CTASK] RegTask FAILED");
    return ERR_TASKBSY;
}

static void UnregTask(TaskObj* taskSlot)
{
    // 回收任务内存、重置状态
    taskSlot->dataBody = NULL;
    taskSlot->sta = IDLE;
    taskSlot->exe = NULL;
    taskSlot->len = 0;
}
